/**
 * Copyright (C), 2015-2019, XXX有限公司
 * FileName: PayApiServiceImpl
 * Author:   wh
 * Date:     2019/5/13 18:29
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.itcs.eureka.service.impl;

import com.alibaba.fastjson.JSON;
import com.itcs.eureka.config.FeignClientConfig;
import com.itcs.eureka.config.FeignClientsProperties;
import com.itcs.eureka.exception.TranBusException;
import com.itcs.eureka.service.PayApiFeignClientService;
import com.itcs.eureka.service.PayApiService;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import feign.Contract;
import feign.Feign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: ITCS_CLOUD
 * @ClassName: PayApiServiceImpl
 * @Description:
 * @author: wanghui
 * @date: 2019/5/13 18:29
 * @Version: 1.0.0
 */
@Slf4j
@Service("payApi")
public class PayApiServiceImpl implements PayApiService {

    @Autowired
    private FeignClientsProperties feignClientsProperties;

    /**
     * FeignClientFactoryBean 该工厂类中 设置builder属性时就是通过该对象，源码中可看到
     */
    @Autowired
    private FeignContext feignContext;

    /**
     * 通过注入Eureka实例对象，就不用手动指定url，只需要指定服务名即可
     */
    @Autowired
    private EurekaClient eurekaClient;

    private Map<String, PayApiFeignClientService> feignClientMap;

    @Override
    public Map<String, Object> exchange(PayApiFeignClientService feignClient,
                                        String trancode, Map<String, Object> reqData) throws Exception {
        log.info("接收Eureka请求:{}[{}]", trancode, JSON.toJSONString(reqData));
        Map<String, Object> res = null;
        try {
            Map<String, Object> reqRecord = new HashMap<>();
            reqRecord.put("req_msg", JSON.toJSONString(reqData));
            res = feignClient.exchange(null, null, reqRecord);
        } catch (TranBusException e) {
            log.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(trancode + ",请求调用失败:" + e.getMessage(), e);
            throw new TranBusException("999999", trancode + ",请求调用失败:" + e.getMessage());
        }
        return res;
    }

    /**
     * 初始化Feign通用接口适配器
     *
     * @param applicationContext
     */
    private void initEurekaServiceAdapters(ApplicationContext applicationContext) {
        Map<String, FeignClientConfig> propertiesMap = feignClientsProperties.getPaychannel();
        propertiesMap.forEach((k, v) -> {
            String serverId = v.getName();
            InstanceInfo nextServerFromEureka = eurekaClient.getNextServerFromEureka(serverId,false);
            PayApiFeignClientService feign = Feign.builder()
                    .encoder(feignContext.getInstance(v.getName(),feign.codec.Encoder.class))
                    .decoder(feignContext.getInstance(serverId,feign.codec.Decoder.class))
                    .contract(feignContext.getInstance(serverId, Contract.class))
                    .target(PayApiFeignClientService.class, nextServerFromEureka.getHomePageUrl());
            feignClientMap.put(serverId,feign);
        });
    }
}
